#include "PreciseSpectrum.h"

PreciseSpectrum::PreciseSpectrum(): myCommonOptions(new CommonOptions()) {}

bool PreciseSpectrum::serialize(QDomElement& elem, QDomDocument& doc) const {
    QDomElement headerElement = doc.createElement("header");
    QDomElement senseElement = doc.createElement("sense");
    QDomElement commonElement = doc.createElement("common");

    //TODO: serialize header

    for (int i = 0; i < this->length(); ++i) {
        QDomElement regionElement = doc.createElement("region");
        if (!at(i)->serialize(regionElement, doc)) {
            return false;
        }
        senseElement.appendChild(regionElement);
    }

    if (!commonOptions()->serialize(commonElement, doc)) {
        return false;
    }

    elem.appendChild(headerElement);
    elem.appendChild(senseElement);
    elem.appendChild(commonElement);
    return true;
}

bool PreciseSpectrum::deserialize(const QDomElement& elem) {
    if (elem.tagName() != "control") {
        return false;
    }
    QDomNodeList headerList = elem.elementsByTagName("header");
    if (headerList.count() != 1) {
        return false;
    }
    QDomElement headerNode = headerList.at(0).toElement();
    if (headerNode.isNull()) {
        return false;
    }
    QDomNodeList senseList = elem.elementsByTagName("sense");
    if (senseList.count() != 1) {
        return false;
    }
    QDomElement senseNode = senseList.at(0).toElement();
    if (senseNode.isNull()) {
        return false;
    }
    QDomNodeList commonList = elem.elementsByTagName("common");
    if (commonList.count() != 1) {
        return false;
    }
    QDomElement commonNode = commonList.at(0).toElement();
    if (commonNode.isNull()) {
        return false;
    }

    //TODO: deserialize header

    for (unsigned short i = 1; i <= 20; ++i) {
        QString tagName("region");
        tagName += QString::number(i);
        QDomNodeList regionList = senseNode.elementsByTagName(tagName);
        if (regionList.count() != 1) {
            return false;
        }
        QDomElement regionNode = regionList.at(0).toElement();
        if (regionNode.isNull()) {
            return false;
        }
        QSharedPointer<PointPairListPlus> pplp(new PointPairListPlus(tagName));
        if (!pplp->deserialize(regionNode, i)) {
            return false;
        }
        append(pplp);
    }

    if (!myCommonOptions->deserialize(commonNode)) {
        return false;
    }

    return true;
}

bool PreciseSpectrum::distract(const QSharedPointer<PreciseSpectrum>& other) {
    QList<QSharedPointer<PointPairListPlus> > temp;
    for (int i = 0; i < 20; ++i) {
        QString tagName("region");
        tagName += QString::number(i + 1);
        QSharedPointer<PointPairListPlus> pplp(new PointPairListPlus(tagName));
        if (!distract(at(i), other->at(i), pplp)) {
            return false;
        }
        temp.append(pplp);
    }

    for (int i = 0; i < 20; ++i) {
        at(i)->setData(temp.at(i)->data());
    }
    append(temp);
    return true;
}

bool PreciseSpectrum::distract(const QSharedPointer<PointPairListPlus>& from, const QSharedPointer<PointPairListPlus>& what, QSharedPointer<PointPairListPlus>& res) {
    if (from->PEDreference()->step() == 0 && what->PEDreference()->step() == 0) {
        //both empty peaks
        return true;
    }
    if (!from->PEDreference()->equals(*(what->PEDreference()))) {
        return false;
    }
    if (from->dataSize() != what->dataSize()) {
        return false;
    }
    QVector<double> xs;
    QVector<double> ys;
    for (int i = 0; i < from->dataSize(); ++i) {
        if (from->x(i) != what->x(i)) {
            return false;
        }
        xs.append(from->x(i));
        ys.append(from->y(i) - what->y(i));
    }
    res->setData(xs, ys);
    return true;
}
